package main

import (
	"log"
	"sync"
	"time"
)

// 带缓冲区 channel：用作计数信号量（counting semaphore）
// 示例：同一时间最多允许 3 个活跃的 goroutine 在处理任务

var active = make(chan struct{}, 3)
var jobs = make(chan int, 10)

func main() {
	go func() {
		for i := 0; i < 8; i++ {
			jobs <- (i + 1)
		}
		close(jobs)
	}()

	var wg sync.WaitGroup
	for j := range jobs {
		wg.Add(1)
		go func(n int) {
			active <- struct{}{} // 同一时间最多允许3个 goroutine 处理任务，当缓冲区容量满了，新的 goroutine 会在这里阻塞

			log.Printf("job-%d is executing", n)

			time.Sleep(1 * time.Second)

			<-active // 缓冲区当前活跃 goroutine 的数量 -1

			wg.Done()
		}(j)
	}

	wg.Wait()
}
